import React from "react";
import { screen } from "@testing-library/react";
import { createCustomRenderer } from "test/test-utils";
import {
  createMockSoftwarePackage,
  createMockSoftwareTitle,
} from "__mocks__/softwareMock";
import softwareAPI from "services/entities/software";
import EditIconModal from "./EditIconModal";

const software = createMockSoftwareTitle();
const softwarePackage = createMockSoftwarePackage();
const MOCK_PROPS = {
  softwareId: 123,
  teamIdForApi: 456,
  software: softwarePackage,
  onExit: jest.fn(),
  refetchSoftwareTitle: jest.fn(),
  iconUploadedAt: "2025-09-03T12:00:00Z",
  setIconUploadedAt: jest.fn(),
  installerType: "package" as "package" | "vpp",
  previewInfo: {
    type: "apps",
    versions: software.versions?.length,
    source: software.source,
    currentIconUrl: null,
    name: software.name,
    titleName: software.name,
    countsUpdatedAt: "2025-09-03T12:00:00Z",
  },
};

describe("EditIconModal", () => {
  it("renders with the correct modal title for software, FileUploader, Preview tabs, save button", () => {
    const render = createCustomRenderer({ withBackendMock: true });
    render(<EditIconModal {...MOCK_PROPS} />);

    expect(screen.getByText(/edit software/i)).toBeInTheDocument();
    expect(screen.getByText("Choose file")).toBeInTheDocument();
    expect(screen.getByText("Preview")).toBeInTheDocument();
    expect(screen.getByText("Fleet")).toBeInTheDocument();
    expect(screen.getByText("Self-service")).toBeInTheDocument();
    const save = screen.getByRole("button", { name: "Save" });
    expect(save).toBeInTheDocument();
  });

  it("shows the correct software name and preview info in Fleet card", () => {
    const render = createCustomRenderer({ withBackendMock: true });
    render(<EditIconModal {...MOCK_PROPS} />);
    expect(screen.getAllByText(software.name).length).toBeGreaterThan(0);
    expect(screen.getByText("Version")).toBeInTheDocument();
    expect(screen.getByText("Vulnerabilities")).toBeInTheDocument();
    expect(screen.getByText("88.0.1")).toBeInTheDocument();
    expect(screen.getByText("20 vulnerabilities")).toBeInTheDocument();
  });

  it("calls onExit handler when modal close is triggered", async () => {
    const render = createCustomRenderer({ withBackendMock: true });
    const { user } = render(<EditIconModal {...MOCK_PROPS} />);

    await user.keyboard("{Escape}");

    expect(MOCK_PROPS.onExit).toHaveBeenCalled();
  });

  // Note: Rely on QA Wolf for E2e testing of file upload, preview, save, and remove icon

  describe("Display name tests", () => {
    it("shows the Display name input with correct default value", () => {
      const render = createCustomRenderer({ withBackendMock: true });
      render(<EditIconModal {...MOCK_PROPS} />);
      // Should default to blank if previewInfo.titleName === previewInfo.name
      const displayNameInput = screen.getByLabelText("Display name");
      expect(displayNameInput).toBeInTheDocument();
      expect(displayNameInput).toHaveValue("");
    });

    it("pre-fills Display name if previewInfo.name has been modified", () => {
      const MODIFIED_PROPS = {
        ...MOCK_PROPS,
        previewInfo: {
          ...MOCK_PROPS.previewInfo,
          name: "New Custom Name",
          titleName: "Original Title Name",
        },
      };
      const render = createCustomRenderer({ withBackendMock: true });
      render(<EditIconModal {...MODIFIED_PROPS} />);
      const displayNameInput = screen.getByLabelText("Display name");
      expect(displayNameInput).toBeInTheDocument();
      expect(displayNameInput).toHaveValue("New Custom Name");
      const helpText = screen.getByText(
        /Optional. If left blank, Fleet will use/
      );

      expect(helpText).toHaveTextContent(MODIFIED_PROPS.previewInfo.titleName);
    });

    it("only edits the display name when icon is not changed", async () => {
      const editSoftwarePackageSpy = jest
        .spyOn(softwareAPI, "editSoftwarePackage")
        .mockResolvedValue({} as any);
      const deleteSoftwareIconSpy = jest.spyOn(
        softwareAPI,
        "deleteSoftwareIcon"
      );
      const editSoftwareIconSpy = jest.spyOn(softwareAPI, "editSoftwareIcon");

      const render = createCustomRenderer({ withBackendMock: true });
      const { user } = render(<EditIconModal {...MOCK_PROPS} />);

      const displayNameInput = screen.getByLabelText("Display name");
      await user.type(displayNameInput, "New Name     ");

      const saveButton = screen.getByRole("button", { name: "Save" });
      await user.click(saveButton);

      expect(editSoftwarePackageSpy).toHaveBeenCalledWith({
        data: { displayName: "New Name" }, // whitespace was trimmed
        softwareId: 123,
        teamId: 456,
      });

      expect(deleteSoftwareIconSpy).not.toHaveBeenCalled();
      expect(editSoftwareIconSpy).not.toHaveBeenCalled();
    });

    it("only edits the display name when removing a custom name", async () => {
      const editSoftwarePackageSpy = jest
        .spyOn(softwareAPI, "editSoftwarePackage")
        .mockResolvedValue({} as any);

      const MODIFIED_PROPS = {
        ...MOCK_PROPS,
        previewInfo: {
          ...MOCK_PROPS.previewInfo,
          name: "Custom Display Name",
          titleName: "Original Software Name",
        },
      };

      const render = createCustomRenderer({ withBackendMock: true });
      const { user } = render(<EditIconModal {...MODIFIED_PROPS} />);

      const displayNameInput = screen.getByLabelText("Display name");
      await user.clear(displayNameInput);

      const saveButton = screen.getByRole("button", { name: "Save" });
      await user.click(saveButton);

      expect(editSoftwarePackageSpy).toHaveBeenCalledWith({
        data: { displayName: "" },
        softwareId: 123,
        teamId: 456,
      });
    });

    it("handles name update error properly", async () => {
      const editSoftwarePackageSpy = jest
        .spyOn(softwareAPI, "editSoftwarePackage")
        .mockRejectedValue(new Error("Name update failed"));

      const CUSTOM_ICON_PROPS = {
        ...MOCK_PROPS,
        previewInfo: {
          ...MOCK_PROPS.previewInfo,
          currentIconUrl: null,
        },
      };

      const render = createCustomRenderer({ withBackendMock: true });
      const { user } = render(<EditIconModal {...CUSTOM_ICON_PROPS} />);

      const displayNameInput = screen.getByLabelText("Display name");
      await user.type(displayNameInput, "New Name");

      const saveButton = screen.getByRole("button", { name: "Save" });
      await user.click(saveButton);

      expect(editSoftwarePackageSpy).toHaveBeenCalled();
      await expect(editSoftwarePackageSpy).rejects.toThrow(
        "Name update failed"
      );
    });
  });
});
